import { useRef, useState, useMemo, useCallback } from "react";
import set from "lodash/set";
import get from "lodash/get";
import { useForm } from "./metadata-context";
import Schema from "async-validator";
import useFieldLifecycle from "../lifecycle/useFieldLifecycle";
import eventBus from "../eventBus";
import { useInject } from "./inject-context";

/**
 * 
 * @param {string} field 字段唯一路径 
 * @param {Array} rules 校验规则扩展
 * @param {Function} onChanged 值变化后的扩展
 * @param {Function} displayFormatter 显示值特殊处理扩展
 * @param {Function} valueFormatter 实际值特处理扩展 
 * @param {Function} onBlured 字段失去焦点后的扩展
 * @param {Boolean} triggerBlurAsChange 当值变化时是否触发失去焦点事件
 * @param {Boolean} alwaysTriggerChange 字段值发生变化后，不管是否跟旧的值一样，始终触发一次onchange事件
 */
function useFormField({ field, rules = [], onChanged, displayFormatter, valueFormatter, onBlured, triggerBlurAsChange = false, alwaysTriggerChangeEvt = false}) {
  const [updaterObject, setState] = useState({});
  const updater = useCallback((value) => setState(value), []);
  const metadataManager = useForm();
  const injectInfo = useInject();
  const isValidatingRef = useRef(false); //是否正在校验
  const validationRef = useRef({}); //校验信息
  const touchedRef = useRef(false);//是否touched过
  if (updaterObject.current == true) {
    touchedRef.current = true;
    updaterObject.current = undefined;
  }

  const {validateWithTouch } = metadataManager.root;
  let o = {};
  const formData = metadataManager.data || o;
  let rootForm = metadataManager.root || o;

  //注册字段生命周期
  useFieldLifecycle(metadataManager, field, updater);

  //如果设计器勾选了必填项,并且是编辑模式
  if (injectInfo?.isDefaultRequired === true) {
    if (rules.length === 0 || rules.find((r) => r.required !== true)) {
      rules.push({
        required: true,
        message: "请输入",
      });
    }
  } else {
    const ruleIndex = rules.findIndex((r) => r.required === true);
    if (ruleIndex > -1) rules.splice(ruleIndex, 1);
  }

  //初始化Property
  if (rootForm.property == undefined) {
    rootForm.property = {};
  }

  if (updaterObject.value !== undefined) {

    function triggerChange(){
        eventBus.publish(`field.change.${field}`, updaterObject.value);
        if (triggerBlurAsChange) {
          eventBus.publish("field.blur", field, updaterObject.value, injectInfo?.rowIndex);
        }
      
    }
    
    //字段触发更新时，如果新的value跟旧的value不一致，才触发相关事件，进行节流处理
    if (get(formData, field) !== updaterObject.value) {
      if (valueFormatter) {
        set(formData, field, valueFormatter(updaterObject.value));
      } else {
        set(formData, field, updaterObject.value);
      }

      if(alwaysTriggerChangeEvt === false){
        triggerChange();
      }

    }

    //如果配置了始终触发字段的change事件，则直接触发onchange，目前只有数据互联字段才有这个属性配置
    if(alwaysTriggerChangeEvt === true){
      triggerChange();
    }

    delete updaterObject.value;
  }

  //获取字段表单值
  let value = get(formData, field);
  let formattedValue;
  if (displayFormatter) {
    //进行拦截处理显示逻辑
    formattedValue = displayFormatter(value, formData);
  }
  let isDisplay= (rootForm.isDisplay || injectInfo?.isEditable === false);

  useMemo(() => {
    if (isDisplay !== true) {
      let myRule = rules;
      //发起协商 回复协商 交办 驳回 不同意 终止 不校验表单正确性
      //fixme 这段代码应该放入表单上下文对象内
      if(~["Consult", "ReplyConsult", "Assigned", "RollBack", "Cancel", "Terminate"].indexOf(formData.__approveType__)){
        console.log("发起协商 回复协商 交办 驳回 不同意 终止 不校验表单正确性");
        myRule=[];
      }
      //当前字段可编辑
      validate(field, metadataManager, myRule, value, isValidatingRef); //触发校验
      
    }
  }, [value, field, metadataManager.root.forceUpdate, injectInfo?.isDefaultRequired]);

  let propertyError = rootForm.property?.hasError?.[field];
  if (((validateWithTouch && touchedRef.current && isValidatingRef.current == false) || validateWithTouch == false) && propertyError) {
    validationRef.current = {
      validateStatus: "error",
      help: propertyError,
    };
  } else {
    validationRef.current = {};
  }
  const onChange = (e, data, extra) => {
    let newValue;
    if (e && e._d && data) {
      //后端接收的是原始字符串DatePicker
      newValue = data;
    } else {
      newValue = e && e.target ? (e.target.type == "checkbox" ? e.target.checked : e.target.value) : e;
    }

    if (value !== newValue) {
      //实际值特处理扩展 
      if (valueFormatter) {
        set(formData, field, valueFormatter(newValue));
      } else {
        set(formData, field, newValue);
      }

      onChanged && onChanged(newValue, value, data, metadataManager);

      //静默修改
      if(extra?.isSilence!==true){
        touchedRef.current = true;
      }
  
      updater({});

      //发送值改变事件
      eventBus.publish(`field.change.${field}`, newValue);
      if (triggerBlurAsChange) {
        eventBus.publishAsync("field.blur", field, newValue, injectInfo?.rowIndex);
      }
      metadataManager.onChange && metadataManager.onChange(newValue, value, field, data, metadataManager.data, metadataManager);
    }
  };

  const onBlur = (e) => {
    touchedRef.current = true;
    updater({});
    onBlured && onBlured(e, metadataManager);
    if (triggerBlurAsChange !== true) {
      //发布字段blur事件
      eventBus.publishAsync("field.blur", field, value, injectInfo?.rowIndex)
    }
  };
  let readonly = {};
  // if (isReadonly === true) {
  //   readonly.disabled = true;
  // }

  return {
    property: {},
    validation: validationRef.current,
    input: {
      value: formattedValue ? formattedValue : value === "" ? undefined : value,
      onChange,
      onBlur,
    },
    readonly,
    isDisplay,
    className: validationRef.current.validateStatus === "error" ? "has-error " : " ",
  };
}

/**
 * 
 * @param {String} field 字段唯一路径 
 * @param {Object} metadataManager 表单元数据上下文对象
 * @param {*} rules 校验规则
 * @param {*} value 当前字段值
 * @param {*} isValidatingRef 是否正在校验中
 */
function validate(field, metadataManager, rules = [], value, isValidatingRef) {

  isValidatingRef.current = true;
  let hasError = false;
  let firstErrorMessage;
  for (let index = 0; index < rules.length; index++) {
    const rule = rules[index];
    const validator = new Schema({ [field]: rule });

    validator.validate({ [field]: value }, (errors, fields) => {
      if (errors) {
        hasError = true;
        //记录遇到的第一个错误信息
        if (firstErrorMessage == undefined) {
          firstErrorMessage = errors[0].message;
        }
      }
    });
    if (hasError) {
      break;
    }
  }

  //fix php 序列号转换问题
  if (metadataManager.property.hasError == undefined || typeof metadataManager.property.hasError == "boolean" || Array.isArray(metadataManager.property.hasError)) {
    metadataManager.property.hasError = {};
  }

  //把错误信息记录在hasError里面
  if (hasError) {
    metadataManager.property.hasError[field] = firstErrorMessage || {};
  } else {
    //如果没有错误，清除之前的错误信息
    delete metadataManager.property.hasError[field];
  }

  isValidatingRef.current = false;
}

export { useFormField };
